package com.ruoyi.galaxy.util;

public class BitConvert {
    private final static char[] HEX_SYMBOLS = "0123456789ABCDEF".toCharArray();

    public static byte[] getBytes( boolean x ) {
        return new byte[] { (byte) ( x ? 1 : 0 ) };
    }

    public static byte[] getBytes( char c ) {
        return new byte[] { (byte) ( c & 0xff ), (byte) ( c >> 8 & 0xff ) };
    }

    public static byte[] getBytes( double x ) {
        return getBytes( Double.doubleToRawLongBits( x ) );
    }

    public static byte[] getBytes( short x ) {
        return new byte[] { (byte) ( x >>> 8 ), (byte) x };
    }

    public static byte[] getBytes( int x ) {
        return new byte[] { (byte) ( x >>> 24 ), (byte) ( x >>> 16 ), (byte) ( x >>> 8 ), (byte) x };
    }

    public static byte[] getBytes( long x ) {
        return new byte[] { (byte) ( x >>> 56 ), (byte) ( x >>> 48 ), (byte) ( x >>> 40 ), (byte) ( x >>> 32 ),
                (byte) ( x >>> 24 ), (byte) ( x >>> 16 ), (byte) ( x >>> 8 ), (byte) x };
    }

    public static byte[] getBytes( float x ) {
        return getBytes( Float.floatToRawIntBits( x ) );
    }

    public static byte[] getBytes( String x ) {
        return x.getBytes();
    }

    public static long doubleToInt64Bits( double x ) {
        return Double.doubleToRawLongBits( x );
    }

    public static double int64BitsToDouble( long x ) {
        return (double) x;
    }

    public boolean toBoolean( byte[] bytes, int index )
            throws Exception {
        if ( bytes.length != 1 )
            throw new Exception( "The length of the byte array must be at least 1 byte long." );
        return bytes[index] != 0;
    }

    public char toChar( byte[] bytes, int index )
            throws Exception {
        if ( bytes.length != 2 )
            throw new Exception( "The length of the byte array must be at least 2 bytes long." );
        return (char) ( ( 0xff & bytes[index] ) << 8 | ( 0xff & bytes[index + 1] ) << 0 );
    }

    public double toDouble( byte[] bytes, int index )
            throws Exception {
        if ( bytes.length != 8 )
            throw new Exception( "The length of the byte array must be at least 8 bytes long." );
        return Double.longBitsToDouble( toInt64( bytes, index ) );
    }

    public static short toInt16( byte[] bytes, int index )
            throws Exception {
        if ( bytes.length != 8 )
            throw new Exception( "The length of the byte array must be at least 8 bytes long." );
        return (short) ( ( 0xff & bytes[index] ) << 8 | ( 0xff & bytes[index + 1] ) << 0 );
    }

    public static int toInt32( byte[] bytes, int index )
            throws Exception {
        if ( bytes.length != 4 )
            throw new Exception( "The length of the byte array must be at least 4 bytes long." );
        return (int) ( (int) ( 0xff & bytes[index] ) << 56 | (int) ( 0xff & bytes[index + 1] ) << 48
                | (int) ( 0xff & bytes[index + 2] ) << 40 | (int) ( 0xff & bytes[index + 3] ) << 32 );
    }

    public static long ToUInt32( byte[] bytes, int index ) {
        long result = (int) bytes[index] & 0xff << 24;
        result |= ( (int) bytes[index + 1] & 0xff ) << 16;
        result |= ( (int) bytes[index + 2] & 0xff ) << 8;
        result |= ( (int) bytes[index + 3] & 0xff );
        return result & 0xFFFFFFFFL;
    }

    public static long toInt64( byte[] bytes, int index )
            throws Exception {
        if ( bytes.length != 8 )
            throw new Exception( "The length of the byte array must be at least 8 bytes long." );
        return (long) ( (long) ( 0xff & bytes[index] ) << 56 | (long) ( 0xff & bytes[index + 1] ) << 48
                | (long) ( 0xff & bytes[index + 2] ) << 40 | (long) ( 0xff & bytes[index + 3] ) << 32
                | (long) ( 0xff & bytes[index + 4] ) << 24 | (long) ( 0xff & bytes[index + 5] ) << 16
                | (long) ( 0xff & bytes[index + 6] ) << 8 | (long) ( 0xff & bytes[index + 7] ) << 0 );
    }

    public static float toSingle( byte[] bytes, int index )
            throws Exception {
        if ( bytes.length != 4 )
            throw new Exception( "The length of the byte array must be at least 4 bytes long." );
        return Float.intBitsToFloat( toInt32( bytes, index ) );
    }

    public static String toString( byte[] bytes )
            throws Exception {
        if ( bytes == null )
            throw new Exception( "The byte array must have at least 1 byte." );
        return new String( bytes );
    }

    public static String urlEncode(byte[] bytes) {

        StringBuilder buf = new StringBuilder();
        for (byte b : bytes) {
            char c = (char) b;
            if   ( (c >= 48 && c <= 57) // 0-9
                    || (c >= 65 && c <= 90) // A-Z
                    || (c >= 97 && c <= 122) // a-z
                    ||  c == 45  // -
                    ||  c == 46  // .
                    ||  c == 95  // _
                    ||  c == 126 // ~
            ) {
                buf.append(c);
            } else {
                buf.append("%");
                String hex = Integer.toHexString(b & 0xFF).toUpperCase();
                if (hex.length() == 1) {
                    buf.append("0");
                }
                buf.append(hex);
            }
        }
        return buf.toString();
    }

    /**
     * Convert a byte string to a string containing an hexadecimal
     * representation of the original data.
     *
     * @param bytes The byte array to convert.
     */
    public static String byteArrayToHexString(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = HEX_SYMBOLS[v >>> 4];
            hexChars[j * 2 + 1] = HEX_SYMBOLS[v & 0x0F];
        }
        return new String(hexChars);
    }
}
